﻿using System;
using System.Collections.Generic;
using System.Linq;
using Data.Entity;
using Service;

namespace ECommerce.Controls
{
	public partial class Tags : BaseUserControl
	{
		private IProductTagService _ProductTagService;

		double _mean;
		double _stdDev;
		protected void Page_PreRender(object sender, EventArgs e)
		{
			this.LTagsHeaderLabel.Text = GetLocalResourceString("Tags.HeaderLabel");

			if (SiteContext.Current != null && SiteContext.Current.WorkingLanguage != null)
			{
				BindData();
			}
		}

		protected void BindData()
		{
			if (_ProductTagService == null)
			{
				_ProductTagService = new ProductTagService();
			}

			//get all tags
			int maxItems = 15;
			var productTags = _ProductTagService.GetProductTagByLanguage(SiteContext.Current.WorkingLanguage.LanguageId);

			if (productTags == null)
			{
				RepeaterTags.DataSource = null;
				RepeaterTags.DataBind();

				return;
			}

			List<ProductTag> cloudItems = new List<ProductTag>();
			for (int i = 0; i < productTags.Count; i++)
			{
				ProductTag productTag = productTags[i];
				if (i < maxItems)
				{
					cloudItems.Add(productTag);
				}
			}

			//calculate weights
			_mean = 0;
			List<double> itemWeights = new List<double>();
			foreach (var productTag in cloudItems)
			{
				itemWeights.Add(productTag.ProductCount);
			}
			_stdDev = StdDev(itemWeights, out _mean);

			foreach (var productTag in cloudItems)
			{
				int fontSize = GetFontSize(productTag.ProductCount, _mean, _stdDev);
			}

			//sorting
			cloudItems.Sort(new ProductTagComparer());

			//binding
			if (cloudItems.Count > 0)
			{
				RepeaterTags.DataSource = cloudItems;
				RepeaterTags.DataBind();
			}
			else
			{
				this.Visible = false;
			}
		}

		protected int GetFontSize(double weight, double mean, double stdDev)
		{
			double factor = (weight - mean);

			if (factor != 0 && stdDev != 0)
				factor /= stdDev;

			return (factor > 2) ? 150 :
				(factor > 1) ? 120 :
				(factor > 0.5) ? 100 :
				(factor > -0.5) ? 90 :
				(factor > -1) ? 85 :
				(factor > -2) ? 80 :
				75;
		}

		protected int GetFontSize(int productCount)
		{
			int result = GetFontSize(productCount, _mean, _stdDev);
			return result;
		}

		protected double Mean(IEnumerable<double> values)
		{
			double sum = 0;
			int count = 0;

			foreach (double d in values)
			{
				sum += d;
				count++;
			}

			return sum / count;
		}

		protected double StdDev(IEnumerable<double> values, out double mean)
		{
			mean = Mean(values);
			double sumOfDiffSquares = 0;
			int count = 0;

			foreach (double d in values)
			{
				double diff = (d - mean);
				sumOfDiffSquares += diff * diff;
				count++;
			}

			return Math.Sqrt(sumOfDiffSquares / count);
		}

		protected double StdDev(IEnumerable<double> values)
		{
			double mean;
			return StdDev(values, out mean);
		}

		protected class ProductTagComparer : IComparer<ProductTag>
		{
			public int Compare(ProductTag x, ProductTag y)
			{
				if (y == null || String.IsNullOrEmpty(y.Name))
					return -1;
				if (x == null || String.IsNullOrEmpty(x.Name))
					return 1;
				return x.Name.CompareTo(y.Name);
			}
		}
	}
}